package io.renren.utils;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baidu.aip.ocr.AipOcr;
import io.renren.entity.dto.BaiduOcrResponse;
import io.renren.entity.dto.OcrResultBo;
import io.renren.entity.dto.WordsResultBean;
import lombok.extern.slf4j.Slf4j;
import org.json.JSONObject;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: hongyuliu
 * @Date: 2020-07-27
 * @Version 1.0
 */
@Slf4j
public class BaiduOcrUtils {

    private static String getTheLongestChineseString(String target) {
        if (StrUtil.isNotBlank(target)) {
            List<String> queryList = ReUtil.findAll("[\\u4e00-\\u9fa5]{4}", target, 0, new ArrayList());
            if (CollectionUtil.isNotEmpty(queryList)) {
                log.info("关键字：[{}]---------原句子：[{}]----", queryList.get(0), target);
                return queryList.get(0);
            }
        }
        return null;
    }

    /**
     * 获取英文最长子串
     *
     * @param target
     * @return
     */
    private static List<String> getTheLongestEnglishString(String target) {
        if (StrUtil.isNotBlank(target)) {
            String[] strings = target.split("[\\u4e00-\\u9fa5]");

            List<String> queryList = Arrays.stream(strings)
                    .filter(StrUtil::isNotBlank)
                    .map(s -> s.split(" "))
                    .flatMap(Arrays::stream)
                    .filter(s -> {
                        byte[] bytes = s.getBytes();
                        for (byte b : bytes) {
                            if (!Character.isLetter(b)) {
                                return false;
                            }
                        }
                        return true;
                    })
                    .filter(s -> s.length() > 3)
                    .limit(3)
                    .collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(queryList)) {
                log.info("关键字：[{}]---------原句子：[{}]----", queryList, target);
                return queryList;
            }
        }
        return null;
    }

    /**
     * 判断是否为英文卷
     *
     * @param words_result
     * @return
     */
    private static boolean isEnglish(List<WordsResultBean> words_result) {
        String s = words_result.stream()
                .map(WordsResultBean::getWords)
                .collect(Collectors.joining("|"));
        // 获取空格的数量
        String[] split = s.split(" ");
        if (split.length > words_result.size() * 2) {
            return true;
        }
        return false;
    }

    /**
     * 通过输入流获取识别结果
     *
     * @param aipOcr
     * @param url    图片地址
     * @return
     * @throws IOException
     */
    public static OcrResultBo getBaiduOcrResult4Sort(AipOcr aipOcr, String url) {

        HashMap<String, String> options = new HashMap();
        options.put("language_type", "CHN_ENG");
        options.put("detect_direction", "true");
        options.put("detect_language", "true");
        options.put("probability", "true");
        JSONObject jsonObject = aipOcr.basicGeneralUrl(url, options);
        BaiduOcrResponse baiduOcrResponse = JSONUtil.toBean(jsonObject.toString(), BaiduOcrResponse.class);
        List<WordsResultBean> wordsResult = baiduOcrResponse.getWords_result();
        if (CollectionUtil.isEmpty(wordsResult)) {
            return null;
        }
        List<String> keyWordList = getSelectParam(wordsResult);
        String result = wordsResult.stream()
                .map(WordsResultBean::getWords)
                .collect(Collectors.joining("|"));
        OcrResultBo resultBo = new OcrResultBo();
        resultBo.setKeyWordList(keyWordList);
        resultBo.setResult(result);

        return resultBo;

    }

    private static List<String> getSelectParam(List<WordsResultBean> wordsResult) {
        if (isEnglish(wordsResult)) {
            List<String> collect = wordsResult.stream()
                    .sorted((o1, o2) -> {
                        double average = o1.getProbability().getAverage();
                        double average2 = o2.getProbability().getAverage();
                        return Double.compare(average2, average);
                    })
                    .map(WordsResultBean::getWords)
                    .filter(s -> s.length() > 4)
                    .map(BaiduOcrUtils::getTheLongestEnglishString)
                    .filter(CollectionUtil::isNotEmpty)
                    .flatMap(Collection::stream)
                    .filter(StrUtil::isNotBlank)
                    .distinct()
                    .limit(15)
                    .collect(Collectors.toList());
            return collect;

        }
        return wordsResult.stream()
                .sorted((o1, o2) -> {
                    double average = o1.getProbability().getAverage();
                    double average2 = o2.getProbability().getAverage();
                    return Double.compare(average2, average);
                })
                .map(WordsResultBean::getWords)
                .filter(s -> s.length() > 4)
                .map(BaiduOcrUtils::getTheLongestChineseString)
                .filter(StrUtil::isNotBlank)
                .distinct()
                .limit(7)
                .collect(Collectors.toList());
    }

}
